//
// Created by luo on 2022-10-13.
//

#ifndef ARMOR_DETECT_ARMOR_DETECT_H
#define ARMOR_DETECT_ARMOR_DETECT_H

#include "iostream"
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;

#define PI 3.1415926
#define WINDOW_WIDTH 500
#define WINDOW_HEIGHT 500
#define WIDTH 640
#define HEIGHT 480

struct lamp1
{
    RotatedRect lamp1; //
    Point2f led_up = Point2f(0,0);    //灯条上点坐标
    Point2f led_down = Point2f(0,0);  //灯条下点坐标
    cv::Point2f lamp1_point1;         //第一个灯条上下的中心点
    cv::Point2f lamp1_point2;         //第二个灯条上下的中心点
    double lamp1_angle;				  //灯条角度
    float lamp1_width;			      //灯条宽度
    float lamp1_heigth;		          //灯条高度
    float lamp1_area;				  //灯条面积
};

struct lamp2
{
    RotatedRect lamp2;
    Point2f led_up = Point2f(0,0);    //灯条上点坐标
    Point2f led_down = Point2f(0,0);  //灯条下点坐标
    cv::Point2f lamp2_point1;         //第一个灯条上下的中心点
    cv::Point2f lamp2_point2;         //第二个灯条上下的中心点
    double lamp2_angle;				  //灯条角度
    float lamp2_width;			      //灯条宽度
    float lamp2_heigth;		          //灯条高度
    float lamp2_area;				  //灯条面积
};

class Armor
{
public:
    Armor(){}
    ~Armor(){}
    int tx;  				//绝对的坐标 x
    int ty;					//绝对的坐标 y
    int tz;					//绝对的坐标 z
    bool small=false;		//小装甲板
    bool big=false;			//大装甲板
    bool isFind=false;		//装甲板是否找到
    bool isFire=false;		//装甲板是否开火
    int ID=-1;				//装甲板ID
    int type=1;				//装甲板状态 0为错误状态
    int _3lamptype=1;		//装甲板状态 0为错误状态

    float width;			//装甲板宽度
    float heigth;			//装甲板高度
    float w_h_rate;			//装甲板的长宽比
    double angle;			//装甲板角度
    double area;			//装甲板面积
    double distance;		//装甲板四点
    Point2f point[4];    	//装甲板四点
    Point2f armor_center;  	//装甲板中心
    lamp1 _Lamp1;           //装甲板左灯条
    lamp2 _Lamp2;           //装甲板右灯条

    cv::Rect armor_rect;
    std::vector<cv::Point2f > points; //装甲板四点点集

private:

};

class Armor_detection:public Armor
{
public:
    Armor_detection(){}
    ~Armor_detection(){}

    void Init_img_deal(); //读取图片
    void Init_video_deal(); //打开摄像头进行图片读取

    //装甲板识别处理
    cv::Mat Red_base(cv::Mat &frame);
    cv::Mat Red_bin_operate(cv::Mat &frame); //1、图片预处理
    std::vector<std::vector<cv::Point2i>>Find_contour(cv::Mat img); //2、寻找轮廓
    std::vector<cv::RotatedRect> select_lamp(cv::Mat raw_img,std::vector<std::vector<cv::Point2i>>thre_contours);//3、筛选灯条
    std::vector<cv::Point2f> select_armor(std::vector<cv::RotatedRect> lamp_list);//4、筛选装甲板
    bool select_lamp_(cv::Mat raw_img,std::vector<std::vector<cv::Point2i>>thre_contours);
    bool select_armor_(std::vector<cv::RotatedRect> lamp_list);
    void best_armor();

    //ROI算法处理
    cv::Mat roi_cut(cv::Mat frame,std::array<cv::Point2f,2> roi_points); //识别预处理
    std::array<cv::Point2f,4> roi_region(std::vector<cv::Point2f>armor_points,cv::Point2f left_up_points);//若识别到装甲板
    std::array<cv::Point2f,4> roi_move_enlarge(std::array<cv::Point2f,4> roi_points,vector<int> last_scale,
                                       vector<int> now_scale);//调整ROI区域
    std::array<cv::Point2f,4> roi_origin();


private:
    const int min_threashold = 81;
    const int max_threashold = 255;

    cv::Mat raw_img;    //原始图
    cv::Mat init_result; //预处理结果图
    std::vector<std::vector<cv::Point2i>> threshold_contours; //二值图轮廓
    std::vector<cv::RotatedRect> lamp_list; //旋转矩形
    std::vector<cv::Point2f> armor_list; //最优装甲板


};


#endif //ARMOR_DETECT_ARMOR_DETECT_H
